#include "host_graph_sw.h"

#include "he_mem_config.h"


const unsigned cuAttrLut[4][8] = {
		{ATTR_PL_HBM(0),ATTR_PL_HBM(1),ATTR_PL_HBM(2),ATTR_PL_HBM(3),ATTR_PL_HBM(4),ATTR_PL_HBM(5),ATTR_PL_HBM(6),ATTR_PL_HBM(7)},
		{ATTR_PL_HBM(8+0),ATTR_PL_HBM(8+1),ATTR_PL_HBM(8+2),ATTR_PL_HBM(8+3),ATTR_PL_HBM(8+4),ATTR_PL_HBM(8+5),ATTR_PL_HBM(8+6),ATTR_PL_HBM(8+7)},
		{ATTR_PL_HBM(16+0),ATTR_PL_HBM(16+1),ATTR_PL_HBM(16+2),ATTR_PL_HBM(16+3),ATTR_PL_HBM(16+4),ATTR_PL_HBM(16+5),ATTR_PL_HBM(16+6),ATTR_PL_HBM(16+7)},
		{ATTR_PL_HBM(24+0),ATTR_PL_HBM(24+1),ATTR_PL_HBM(24+2),ATTR_PL_HBM(24+3),ATTR_PL_HBM(24+4),ATTR_PL_HBM(24+5),ATTR_PL_HBM(24+6),ATTR_PL_HBM(24+7)},
};

void base_mem_init(cl_context &context)
{
    for (unsigned int i = 0; i < ARRAY_SIZE(local_mem); i++)
    {
        he_mem_init(context, &local_mem[i]);
    }
}

static void gs_mem_init(cl_context &context, gatherScatterDescriptor *gsItem, int cuIndex, void *data)
{
    gsItem->prop[0].id =  MEM_ID_GS_BASE + cuIndex * MEM_ID_GS_OFFSET;
    gsItem->prop[0].name = "cu prop ping";
    gsItem->prop[0].attr = ATTR_HOST_ONLY;//CU_DDR;
    gsItem->prop[0].unit_size = sizeof(prop_t);
    gsItem->prop[0].size_attr = SIZE_IN_VERTEX;
    he_mem_init(context, &gsItem->prop[0]);
    memcpy(gsItem->prop[0].data, data, gsItem->prop[0].size);

    gsItem->prop[1].id =  MEM_ID_GS_BASE + cuIndex * MEM_ID_GS_OFFSET + 2;
    gsItem->prop[1].name = "cu prop pong";
    gsItem->prop[1].attr = ATTR_HOST_ONLY;//CU_DDR;
    gsItem->prop[1].unit_size = sizeof(prop_t);
    gsItem->prop[1].size_attr = SIZE_IN_VERTEX;
    he_mem_init(context, &gsItem->prop[1]);
    memcpy(gsItem->prop[1].data, data, gsItem->prop[1].size);

    gsItem->tmpProp.id =  MEM_ID_GS_BASE + cuIndex * MEM_ID_GS_OFFSET + 1;
    gsItem->tmpProp.name = "cu output tmpProp";
    gsItem->tmpProp.attr = cuAttrLut[cuIndex][6];//CU_DDR;
    gsItem->tmpProp.unit_size = 16*1024*1024;//sizeof(prop_t);
    gsItem->tmpProp.size_attr = SIZE_USER_DEFINE;//SIZE_IN_VERTEX;
    he_mem_init(context, &gsItem->tmpProp);

    gsItem->bitMap.id =  MEM_ID_GS_BASE + cuIndex * MEM_ID_GS_OFFSET + 11;
    gsItem->bitMap.name = "cu output bitMap";
    gsItem->bitMap.attr = cuAttrLut[cuIndex][7];//CU_DDR;
    gsItem->bitMap.unit_size = 16*1024*1024;//sizeof(int);
    gsItem->bitMap.size_attr = SIZE_USER_DEFINE;//SIZE_IN_VERTEX;
    he_mem_init(context, &gsItem->bitMap);
}


void process_mem_init(cl_context &context)
{
    int *vertexScoreMapped =       (int*)get_host_mem_pointer(MEM_ID_VERTEX_SCORE_MAPPED);
    for (int i = 0; i < SUB_PARTITION_NUM; i++)
    {
        gs_mem_init(context, getGatherScatter(i), i, vertexScoreMapped);
    }
}

void partition_mem_init(cl_context &context, int blkIndex, int size, int cuIndex)
{
	//unsigned int size=pa_size;
	printf("partition_mem_init start:%d %d\n",blkIndex,cuIndex);

    int i = blkIndex;
    subPartitionDescriptor *partitionItem  = getSubPartition(i);
    {
        partitionItem->cuIndex = cuIndex;
        partitionItem->edge.id = MEM_ID_PARTITION_BASE + i * MEM_ID_PARTITION_OFFSET;
        partitionItem->edge.name = "partition edge";
        partitionItem->edge.attr = ATTR_HOST_ONLY;//PARTITION_DDR;
        partitionItem->edge.unit_size = size * sizeof(int);
        partitionItem->edge.size_attr = SIZE_USER_DEFINE;
        he_mem_init(context, &partitionItem->edge);

        partitionItem->edgeMap.id = MEM_ID_PARTITION_BASE + i * MEM_ID_PARTITION_OFFSET + 1;
        partitionItem->edgeMap.name = "partition edgeMap";
        partitionItem->edgeMap.attr = ATTR_HOST_ONLY;//PARTITION_DDR;
        partitionItem->edgeMap.unit_size = size * sizeof(int);
        partitionItem->edgeMap.size_attr = SIZE_USER_DEFINE;
        he_mem_init(context, &partitionItem->edgeMap);

        partitionItem->cuIndex = cuIndex;
        partitionItem->edge1.id = MEM_ID_PARTITION_BASE + i * MEM_ID_PARTITION_OFFSET+11;
        partitionItem->edge1.name = "partition edge1";
        partitionItem->edge1.attr = cuAttrLut[cuIndex][0];//PARTITION_DDR;
        partitionItem->edge1.unit_size = size/4 * sizeof(int);
        partitionItem->edge1.size_attr = SIZE_USER_DEFINE;
        he_mem_init(context, &partitionItem->edge1);

        partitionItem->cuIndex = cuIndex;
        partitionItem->edge2.id = MEM_ID_PARTITION_BASE + i * MEM_ID_PARTITION_OFFSET+12;
        partitionItem->edge2.name = "partition edge2";
        partitionItem->edge2.attr = cuAttrLut[cuIndex][1];//PARTITION_DDR;
        partitionItem->edge2.unit_size = size/4 * sizeof(int);
        partitionItem->edge2.size_attr = SIZE_USER_DEFINE;
        he_mem_init(context, &partitionItem->edge2);

        partitionItem->edge3.id = MEM_ID_PARTITION_BASE + i * MEM_ID_PARTITION_OFFSET + 13;
        partitionItem->edge3.name = "partition edge3";
        partitionItem->edge3.attr = cuAttrLut[cuIndex][2];//PARTITION_DDR;
        partitionItem->edge3.unit_size = size/4 * sizeof(int);
        partitionItem->edge3.size_attr = SIZE_USER_DEFINE;
        he_mem_init(context, &partitionItem->edge3);

        partitionItem->edge4.id = MEM_ID_PARTITION_BASE + i * MEM_ID_PARTITION_OFFSET + 14;
        partitionItem->edge4.name = "partition edge4";
        partitionItem->edge4.attr = cuAttrLut[cuIndex][3];//PARTITION_DDR;
        partitionItem->edge4.unit_size = size/4 * sizeof(int);
        partitionItem->edge4.size_attr = SIZE_USER_DEFINE;
        he_mem_init(context, &partitionItem->edge4);

        partitionItem->edgeProp.id = MEM_ID_PARTITION_BASE + i * MEM_ID_PARTITION_OFFSET + 2;
        partitionItem->edgeProp.name = "partition edgeProp";
//#if 1
//        partitionItem->edgeProp.attr = PARTITION_DDR;
//#else
        partitionItem->edgeProp.attr = ATTR_HOST_ONLY;
//#endif
        partitionItem->edgeProp.unit_size = size * sizeof(int);
        partitionItem->edgeProp.size_attr = SIZE_USER_DEFINE;
        he_mem_init(context, &partitionItem->edgeProp);

        partitionItem->csrIndex.id = MEM_ID_PARTITION_BASE + i * MEM_ID_PARTITION_OFFSET + 20;
        partitionItem->csrIndex.name = "partition csrIndex";
        partitionItem->csrIndex.attr = ATTR_HOST_ONLY;//PARTITION_DDR;
        //partitionItem->csrIndex.unit_size = VERTEX_MAX * sizeof(int);
        //partitionItem->csrIndex.size_attr = SIZE_USER_DEFINE;
        partitionItem->csrIndex.unit_size = (32*1024*1024+4096)*sizeof(int);
        partitionItem->csrIndex.size_attr = SIZE_USER_DEFINE;
        he_mem_init(context, &partitionItem->csrIndex);

        partitionItem->csrIndex1.id = MEM_ID_PARTITION_BASE + i * MEM_ID_PARTITION_OFFSET + 21;
        partitionItem->csrIndex1.name = "partition csrIndex1";
        partitionItem->csrIndex1.attr = cuAttrLut[cuIndex][4];//PARTITION_DDR;
        //partitionItem->csrIndex1.unit_size = VERTEX_MAX * sizeof(int);
        //partitionItem->csrIndex1.size_attr = SIZE_USER_DEFINE;
        partitionItem->csrIndex1.unit_size = (32*1024*1024+4096)*sizeof(int);
        partitionItem->csrIndex1.size_attr = SIZE_USER_DEFINE;
        he_mem_init(context, &partitionItem->csrIndex1);

        partitionItem->csrIndex2.id = MEM_ID_PARTITION_BASE + i * MEM_ID_PARTITION_OFFSET + 22;
        partitionItem->csrIndex2.name = "partition csrIndex2";
        partitionItem->csrIndex2.attr = cuAttrLut[cuIndex][5];//PARTITION_DDR;
        //partitionItem->csrIndex2.unit_size = VERTEX_MAX * sizeof(int);
        //partitionItem->csrIndex2.size_attr = SIZE_USER_DEFINE;
        partitionItem->csrIndex2.unit_size = (32*1024*1024+4096)*sizeof(int);
        partitionItem->csrIndex2.size_attr = SIZE_USER_DEFINE;
        he_mem_init(context, &partitionItem->csrIndex2);

        /*partitionItem->csrIndex3.id = MEM_ID_PARTITION_BASE + i * MEM_ID_PARTITION_OFFSET + 23;
        partitionItem->csrIndex3.name = "partition csrIndex3";
        partitionItem->csrIndex3.attr = cuAttrLut[cuIndex][6];//PARTITION_DDR;
        //partitionItem->csrIndex3.unit_size = VERTEX_MAX * sizeof(int);
        //partitionItem->csrIndex3.size_attr = SIZE_USER_DEFINE;
        partitionItem->csrIndex3.unit_size = (16*1024*1024+4096)*sizeof(int);
        partitionItem->csrIndex3.size_attr = SIZE_USER_DEFINE;
        he_mem_init(context, &partitionItem->csrIndex3);

        partitionItem->csrIndex4.id = MEM_ID_PARTITION_BASE + i * MEM_ID_PARTITION_OFFSET + 24;
        partitionItem->csrIndex4.name = "partition csrIndex4";
        partitionItem->csrIndex4.attr = cuAttrLut[cuIndex][7];//PARTITION_DDR;
        //partitionItem->csrIndex4.unit_size = VERTEX_MAX * sizeof(int);
        //partitionItem->csrIndex4.size_attr = SIZE_USER_DEFINE;
        partitionItem->csrIndex4.unit_size = (16*1024*1024+4096)*sizeof(int);
        partitionItem->csrIndex4.size_attr = SIZE_USER_DEFINE;
        he_mem_init(context, &partitionItem->csrIndex4);*/

        partitionItem->tmpProp.id = MEM_ID_PARTITION_BASE + i * MEM_ID_PARTITION_OFFSET + 3;
        partitionItem->tmpProp.name = "partition tmpProp";
        partitionItem->tmpProp.attr = cuAttrLut[cuIndex][6];//PARTITION_DDR;
        //partitionItem->tmpProp.unit_size = VERTEX_MAX * sizeof(prop_t);
        //partitionItem->tmpProp.size_attr = SIZE_USER_DEFINE;
        partitionItem->tmpProp.unit_size = 16*1024*1024;//sizeof(prop_t);
        partitionItem->tmpProp.size_attr = SIZE_USER_DEFINE;//SIZE_IN_VERTEX;
        he_mem_init(context, &partitionItem->tmpProp);
    }
}
